package com.ruoyi.cs.service.impl;

import java.math.BigDecimal;
import java.util.*;
import com.ruoyi.common.core.domain.Response;
import com.ruoyi.cs.domain.*;
import com.ruoyi.cs.domain.vo.PersonalBillVo;
import com.ruoyi.cs.domain.vo.SomisspayVo;
import com.ruoyi.cs.domain.vo.TRechargeVo;
import com.ruoyi.cs.mapper.*;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.pay.HttpsUtils;
import com.ruoyi.common.utils.pay.PayjsConfig;
import com.ruoyi.common.utils.pay.SignUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.cs.service.CommonService;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.mapper.SysDictDataMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.cs.service.ITRechargeService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 充值记录Service业务层处理
 * 
 * @author ruoyi
 * @date 2021-03-25
 */
@Service
@SuppressWarnings("ALL")
public class TRechargeServiceImpl implements ITRechargeService 
{
    private static final Logger log = LoggerFactory.getLogger(TRechargeServiceImpl.class);

    @Autowired
    private TRechargeMapper tRechargeMapper;

    @Autowired
    private TUserMapper tUserMapper;

    @Autowired
    private TUserSyMapper tUserSyMapper;

    @Autowired
    private TBackpackMapper tBackpackMapper;

    @Value("${ruoyi.cznotify}")
    private String cznotify;

    @Autowired
    private TBalanceChangeMapper tBalanceChangeMapper;

    @Autowired
    private SysConfigMapper sysConfigMapper;

    @Autowired
    private SysDictDataMapper sysDictDataMapper;

    @Autowired
    private TUserAuthenticationMapper tUserAuthenticationMapper;

    @Autowired
    private CommonService commonService;

    /**
     * 查询充值记录
     * 
     * @param czId 充值记录ID
     * @return 充值记录
     */
    @Override
    public TRecharge selectTRechargeById(String czId)
    {
        return tRechargeMapper.selectTRechargeById(czId);
    }

    /**
     * 查询充值记录列表
     * 
     * @param tRecharge 充值记录
     * @return 充值记录
     */
    @Override
    public List<TRecharge> selectTRechargeList(TRecharge tRecharge)
    {
        return tRechargeMapper.selectTRechargeList(tRecharge);
    }

    /**
     * 新增充值记录
     * 
     * @param tRecharge 充值记录
     * @return 结果
     */
    @Override
    public int insertTRecharge(TRecharge tRecharge)
    {
        tRecharge.setCreateTime(DateUtils.getNowDate());
        return tRechargeMapper.insertTRecharge(tRecharge);
    }

    /**
     * 修改充值记录
     * 
     * @param tRecharge 充值记录
     * @return 结果
     */
    @Override
    public int updateTRecharge(TRecharge tRecharge)
    {
        tRecharge.setUpdateTime(DateUtils.getNowDate());
        return tRechargeMapper.updateTRecharge(tRecharge);
    }

    /**
     * 批量删除充值记录
     * 
     * @param czIds 需要删除的充值记录ID
     * @return 结果
     */
    @Override
    public int deleteTRechargeByIds(String[] czIds)
    {
        return tRechargeMapper.deleteTRechargeByIds(czIds);
    }

    /**
     * 删除充值记录信息
     * 
     * @param czId 充值记录ID
     * @return 结果
     */
    @Override
    public int deleteTRechargeById(String czId)
    {
        return tRechargeMapper.deleteTRechargeById(czId);
    }

    /**
     * 充值接口
     * @param tRecharge
     * @param response
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public Response<Map> rechargeSomisspay(String userId,BigDecimal czMoney,String czEquipment) throws Exception {

        TUser tUser = tUserMapper.selectTUserById(userId);
        BigDecimal giveFee = new BigDecimal("0");
        try {
            giveFee = commonService.rechargeVerification(tUser, czMoney);
        } catch (Exception e) {
            return Response.fail(e.getMessage());
        }

        //补充充值接口，调取外部补充接口
        String out_trade_no = DateUtils.dateTimeNow() + IdUtils.fastUUID().substring(0, 8);
        /**1金币=6.5元 */
        BigDecimal bg = czMoney;
        BigDecimal fee = bg.multiply(new BigDecimal(6.5)).setScale(2, BigDecimal.ROUND_HALF_UP);
        Map<String, String> payData = new HashMap<>();
        payData.put("version", "1.0");
        payData.put("customerid", PayjsConfig.customerid);
        payData.put("totalfee", fee.toString());
        payData.put("sdorderno", out_trade_no);
        payData.put("notifyurl", cznotify);
        payData.put("returnurl", "http://");
        if (false) {
            payData.put("paytype", "weixinjsapi");
        } else {
            payData.put("paytype", "alipayjsapi");
        }
        payData.put("subject", "lucky");
        payData.put("server", czMoney.toString());
        payData.put("sign", SignUtils.signJH(payData, PayjsConfig.apikey));
        payData.put("qrtype", "string");
        Long starttime = System.currentTimeMillis();
        /**发送请求*/
        String result = HttpsUtils.http(PayjsConfig.somisspayUrl, payData);
        log.info("聚合充值发送请求时间:{}", System.currentTimeMillis() - starttime);

        String picurl = null;
        try {
            /**生产二维码图片*/
            picurl = commonService.scQrCodeImge(result);
        } catch (Exception e) {
            log.error("聚合支付生产二维码订单异常:{}", e.getMessage());
            e.printStackTrace();
            return Response.fail("发送请求失败");
        }

        TRecharge tRecharge = new TRecharge();
        tRecharge.setCzId(out_trade_no);
        tRecharge.setUserId(userId);
        tRecharge.setCzMoney(czMoney);
        tRecharge.setCzPlatform(Constants.CZPLATFORM0);
        tRecharge.setCzEquipment(czEquipment);
        tRecharge.setCzType("1");
        /**支付结果  0 待充值 1充值成功 2充值失败*/
        tRecharge.setCzStatus(Constants.CZSTATUS0);
        tRecharge.setCreateTime(DateUtils.getNowDate());
        tRecharge.setUserType(tUser.getUserType());
        tRecharge.setDelFlag(Constants.SUCCESS);
        tRecharge.setGiveFee(giveFee);
        if (StringUtils.isNotEmpty(tUser.getUserPromotersId())) {
            tRecharge.setUserPromotersId(tUser.getUserPromotersId());
        }
        int count = tRechargeMapper.insertTRecharge(tRecharge);
        if (count > 0) {
            Map map = new HashMap();
            map.put("totalFee", tRecharge.getCzMoney());
            map.put("czId", out_trade_no);
            map.put("picUrl", picurl);
            map.put("url", result);
            return Response.success(map);
        } else {
            log.error("充值记录表插入失败!,错误信息:{}",tRecharge.toString());
            return Response.fail(Constants.FAILCODE, "充值信息添加失败！");
        }
    }

    /**
     * 异步通知接口
     * @param notifyDTO
     * @return
     */
    @Override
    @Transactional
    public Object payjsNotifySomisspay(SomisspayVo vo) {
        try {
            log.error("聚合异步通知参数：{}", vo.toString());
            Map<String, String> notifyData = new HashMap<>();
            notifyData.put("customerid", vo.getCustomerid());
            notifyData.put("totalfee", vo.getTotalfee());
            notifyData.put("sdorderno", vo.getSdorderno());
            notifyData.put("sdpayno", vo.getSdpayno());
            notifyData.put("paytype", vo.getPaytype());

            String sign = SignUtils.signJHNotify(notifyData, PayjsConfig.apikey);
            if (sign.equals(vo.getSign())) {
                // 验签通过，这里修改订单状态
                String id = vo.getSdorderno();
                TRecharge tRecharge = tRechargeMapper.selectTRechargeById(id);
                /**判断金额、金币是否一致、是否为待支付状态*/
                if (tRecharge != null) {
                    BigDecimal bg = tRecharge.getCzMoney();
                    BigDecimal fee = bg.multiply(new BigDecimal(6.5)).setScale(2, BigDecimal.ROUND_HALF_UP);
                    //fee.toString()  0.01
                    if (new BigDecimal(vo.getTotalfee()).compareTo(new BigDecimal(fee.toString())) == 0) {
                        if (tRecharge.getCzStatus().equals(Constants.CZSTATUS0)) {
                            commonService.czSuccessHandle(tRecharge,vo.getSdorderno(),vo.getSdpayno(),vo.toString());
                        } else {
                            log.error("用户聚合充值操作已完成,请求参数:{}", vo.toString());
                        }
                        return "success";
                    } else {
                        /**支付失败*/
                        if (new BigDecimal(vo.getTotalfee()).compareTo(new BigDecimal("0")) == 0) {
                            if (tRecharge.getCzStatus().equals(Constants.CZSTATUS0)) {
                                commonService.czFailHandle(tRecharge,vo.getSdorderno(),vo.getSdorderno(),vo.toString());
                            }
                            return "success";
                        } else {
                            log.error("用户充值异步通知错误，金额对不上 请求参数:{}", vo.toString());
                            return "failure";
                        }
                    }
                }else {
                    log.error("查询充值订单信息为空,请求参数：{}", vo.toString());
                    return "failure";
                }
            }
            log.error("用户聚合充值异步通知算法标签对不上", vo.toString());
            return "failure";
        } catch (Exception e) {
            e.printStackTrace();
            log.error("异步回调异常：{},", e.getMessage());
            return "failure";
        }
    }

    /**
     * 统计充值总金额、总笔数
     * @return
     */
    @Override
    public Map<String, BigDecimal> countTRechargeTotal(TRechargeVo tRechargeVo) {
        /*充值总金额  czMoneyTotal*/
        Map<String, BigDecimal> map = tRechargeMapper.countTRechargeTotalByCondition(tRechargeVo);
        /*统计今日充值总金额  czMoneyToday*/
        Map<String, BigDecimal> map1 = tRechargeMapper.countTRechargeTodayByCondition(tRechargeVo);
        /*今日取回价值统计 retrieveMoneyToday*/
        Map<String, BigDecimal> map2 = tBackpackMapper.retrieveCountTodayByCondition(tRechargeVo);
        /* 历史净利润 profitTotal*/
        BigDecimal goodsPriceTotal = tBackpackMapper.historyGoodsPriceTotal(tRechargeVo);
        BigDecimal userBalanceTotal = tBackpackMapper.userBalanceTotal(tRechargeVo);
        map.putAll(map1);
        map.putAll(map2);
        BigDecimal profitTotal = map.get("czMoneyTotal").subtract(goodsPriceTotal).subtract(userBalanceTotal);
        map.put("profitTotal",profitTotal);
        map.put("profitMoneyTodal",map.get("czMoneyToday").subtract(map.get("retrieveMoneyToday")));
        return map;
    }

    /**
     * 后台充值详情列表
     * @param tRechargeVo
     * @return
     */
    @Override
    public List<TRechargeVo> trechargeListBack(TRechargeVo tRechargeVo) {
        return tRechargeMapper.trechargeListBack(tRechargeVo);
    }

    /**
     * 后台充值列表
     * @param tRechargeCountVo
     * @return
     */
    @Override
    public List<TRechargeVo> listBackCount(TRechargeVo tRechargeVo) {
        List<TRechargeVo> list = tRechargeMapper.listBack(tRechargeVo);
        return list;
    }

    @Override
    public List<PersonalBillVo> getPersonalBill(PersonalBillVo personalBillVo) {
        return tRechargeMapper.getPersonalBill(personalBillVo);
    }
}
